import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import 'package:t3_data_service/biz_data_source/map/address/city_pick/city_pick.dart';

/// CityListView.
class CityListView extends StatefulWidget {
  final List<T3IndexModel> data;
  final int itemCount;
  final IndexedWidgetBuilder itemBuilder;

  final ItemScrollController itemScrollController;
  final ItemPositionsListener itemPositionsListener;

  final IndexedWidgetBuilder? susItemBuilder;
  final double susItemHeight;
  final Offset? susPosition;

  final ScrollPhysics? physics;
  final EdgeInsets? padding;

  const CityListView({
    Key? key,
    required this.data,
    required this.itemCount,
    required this.itemBuilder,
    required this.itemScrollController,
    required this.itemPositionsListener,
    this.susItemBuilder,
    this.susItemHeight = 55.0,
    this.susPosition,
    this.physics,
    this.padding,
  }) : super(key: key);

  @override
  _CityListViewState createState() => _CityListViewState();
}

class _CityListViewState extends State<CityListView> {
  Widget _buildSusWidget(BuildContext context) {
    if (widget.susItemBuilder == null) {
      return Container();
    }
    return ValueListenableBuilder<Iterable<ItemPosition>>(
      valueListenable: widget.itemPositionsListener.itemPositions,
      builder: (ctx, positions, child) {
        if (positions.isEmpty || widget.itemCount == 0) {
          return Container();
        }
        ItemPosition itemPosition = positions
            .where((ItemPosition position) => position.itemTrailingEdge > 0)
            .reduce((ItemPosition min, ItemPosition position) =>
                position.itemTrailingEdge < min.itemTrailingEdge
                    ? position
                    : min);
        if (itemPosition.itemLeadingEdge > 0) return Container();
        int index = itemPosition.index;
        double left = 0;
        double top = 0;
        if (index < widget.itemCount) {
          if (widget.susPosition != null) {
            left = widget.susPosition!.dx;
            top = widget.susPosition!.dy;
          } else {
            int next = math.min(index + 1, widget.itemCount - 1);
            T3IndexModel indexModel = widget.data[next];
            if (indexModel.isShowIndex) {
              double height =
                  context.findRenderObject()?.paintBounds?.height ?? 0;
              double topTemp = itemPosition.itemTrailingEdge * height;
              top = math.min(widget.susItemHeight, topTemp) -
                  widget.susItemHeight;
            }
          }
        } else {
          index = 0;
        }
        return Positioned(
          left: left,
          top: top,
          child: widget.susItemBuilder!(ctx, index),
        );
      },
    );
  }

  Widget _buildItem(BuildContext context, int index) {
    T3IndexModel indexModel = widget.data[index];
    if (!indexModel.isShowIndex || widget.susItemBuilder == null) {
      return widget.itemBuilder(context, index);
    }
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        widget.susItemBuilder!(context, index),
        widget.itemBuilder(context, index),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        widget.itemCount == 0
            ? Container()
            : ScrollablePositionedList.separated(
                itemCount: widget.itemCount,
                itemBuilder: (context, index) => _buildItem(context, index),
                itemScrollController: widget.itemScrollController,
                itemPositionsListener: widget.itemPositionsListener,
                physics: widget.physics,
                padding: widget.padding,
                separatorBuilder: (BuildContext context, int index) {
                  return const Divider(
                    height: 0.5,
                    indent: 15,
                    endIndent: 20,
                  );
                },
              ),
        _buildSusWidget(context),
      ],
    );
  }
}
